package com.ruoyi.flowable.commond;

import static org.flowable.eventregistry.impl.util.CommandContextUtil.getDbSqlSession;

import java.io.Serializable;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Locale;

import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.impl.db.DbSqlSession;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.impl.util.CommandContextUtil;

import com.ruoyi.flowable.model.ColumnCommentMetaData;

public class GetTableColumnCommentInfoCmd implements Command<ColumnCommentMetaData>, Serializable {

    private String tableName;

    public GetTableColumnCommentInfoCmd(String tableName) {
        this.tableName = tableName;
    }

    @Override
    public ColumnCommentMetaData execute(CommandContext commandContext) {
        ColumnCommentMetaData commentMetaData= new ColumnCommentMetaData(tableName);
        DbSqlSession session =  CommandContextUtil.getDbSqlSession(commandContext);
        try {
            DatabaseMetaData metaData = session.getSqlSession().getConnection().getMetaData();
            if ("postgres".equals(session.getDbSqlSessionFactory().getDatabaseType())
                    || "cockroachdb".equals(session.getDbSqlSessionFactory().getDatabaseType())) {
                tableName = tableName.toLowerCase(Locale.ROOT);
            }
            String catalog = getDatabaseCatalog();

            String schema = getDatabaseSchema();

            ResultSet resultSet = metaData.getColumns(catalog, schema,tableName, null);
            while (resultSet.next())
            {
                boolean wrongSchema = false;
                if (schema != null && schema.length() > 0) {
                    for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
                        String columnName = resultSet.getMetaData().getColumnName(i + 1);
                        if ("TABLE_SCHEM".equalsIgnoreCase(columnName) || "TABLE_SCHEMA".equalsIgnoreCase(columnName)) {
                            if (!schema.equalsIgnoreCase(resultSet.getString(resultSet.getMetaData().getColumnName(i + 1)))) {
                                wrongSchema = true;
                            }
                            break;
                        }
                    }
                }
                if (!wrongSchema) {
                    String columnName=resultSet.getString("COLUMN_NAME").toLowerCase(Locale.ROOT);
                    String remark = resultSet.getString("REMARKS").toLowerCase(Locale.ROOT);
                    commentMetaData.addColumnCommentMetaData(columnName,remark);
                }
            }

        } catch (SQLException e) {
            throw new FlowableException("Could not retrieve database metadata: " + e.getMessage());
        }
        if (commentMetaData.getColumnNames().isEmpty()) {
            // According to API, when a table doesn't exist, null should be returned
            commentMetaData = null;
        }
        return commentMetaData;
    }

    protected String getDatabaseCatalog() {
        String catalog = null;
        ProcessEngineConfiguration engineConfiguration= CommandContextUtil.getProcessEngineConfiguration();
        if (engineConfiguration.getDatabaseCatalog() != null && engineConfiguration.getDatabaseCatalog().length() > 0) {
            catalog = engineConfiguration.getDatabaseCatalog();
        }

        return catalog;
    }

    protected String getDatabaseSchema() {
        String schema = null;
        ProcessEngineConfiguration engineConfiguration= CommandContextUtil.getProcessEngineConfiguration();
        if (engineConfiguration.getDatabaseSchema() != null && engineConfiguration.getDatabaseSchema().length() > 0) {
            if ("oracle".equals(getDbSqlSession().getDbSqlSessionFactory().getDatabaseType())) {
                schema = engineConfiguration.getDatabaseSchema().toUpperCase(Locale.ROOT);
            } else {
                schema = engineConfiguration.getDatabaseSchema();
            }
        }

        return schema;
    }



}
